`include "top.vh"

module wb_stage(
    input   wire clk           ,
    input   wire reset         ,
    //allowin
    output wire ws_allowin    ,
    //from ms
    input   wire    ms_to_ws_valid,
    input   wire [`ms_2_ws_bus_wid - 1:0]  ms_to_ws_bus  ,
    //to id
    output wire [38:0]  ws_to_id_bus  ,
    //trace debug interface
    output wire [31:0] debug_wb_pc        ,
    output wire [ 3:0] debug_wb_rf_we ,
    output wire [ 4:0] debug_wb_rf_wnum,
    output wire [31:0] debug_wb_rf_wdata,
    //csr read & write
    output wire [13:0] csr_num,
    input  wire [31:0] csr_rvalue,
    output wire        csr_we_out,
    output wire [31:0] csr_wvalue,
    output wire [31:0] csr_wmask,
    //csr data block
    output wire read_csr,
    //ex
    output wire ws_ex_out,
    output wire ws_ertn_flush,
    output wire [ 5:0] Ecode,
    output wire [ 8:0] EsubCode,
    output wire [31:0] ws_vaddr
);

reg         ws_valid;
wire        ws_ready_go;
reg [ 3:0] ws_sram_we;

wire ws_gr_we;
wire [ 4:0] ws_dest;
wire [31:0] ws_final_result;
wire [31:0] ws_pc;
wire ws_rf_we;
wire        rf_we;
wire [4 :0] rf_waddr;
wire [31:0] rf_wdata;

wire csr_re, csr_we, csr_need_mask;
wire [31:0] csr_wmask_temp;
wire [`CSR_SIG_wid-1:0] csr_signal;
wire ms_ex, ms_ertn;
wire ws_ex, ws_ertn;
wire [`EX_SIG_wid-1:0] ms_ex_signal, ws_ex_signal;

assign ws_ex = ms_ex;
assign ws_ex_signal =   ms_ex ? ms_ex_signal :
                        4'h0;
assign ws_ertn = ms_ertn;

assign read_csr = csr_re && ws_valid;
assign csr_wmask = csr_need_mask ? csr_wmask_temp : 32'hffffffff;
assign csr_we_out = csr_we && ws_valid && !ws_ex;
assign {csr_re, csr_we, csr_need_mask, csr_num, csr_wvalue, csr_wmask_temp} = csr_signal;
assign ws_ertn_flush = ws_ertn && ws_valid;
assign Ecode =  ws_ex_signal == `EX_SIG_INT ?   `ECODE_INT:
                ws_ex_signal == `EX_SIG_PIL ?   `ECODE_PIL:
                ws_ex_signal == `EX_SIG_PIS ?   `ECODE_PIS:
                ws_ex_signal == `EX_SIG_PIF ?   `ECODE_PIF:
                ws_ex_signal == `EX_SIG_PME ?   `ECODE_PME:
                ws_ex_signal == `EX_SIG_PPI ?   `ECODE_PPI:
                ws_ex_signal == `EX_SIG_ADEF?   `ECODE_ADEF:
                ws_ex_signal == `EX_SIG_ADEM?   `ECODE_ADEM:
                ws_ex_signal == `EX_SIG_ALE ?   `ECODE_ALE:
                ws_ex_signal == `EX_SIG_SYS ?   `ECODE_SYS:
                ws_ex_signal == `EX_SIG_BRK ?   `ECODE_BRK:
                ws_ex_signal == `EX_SIG_INE ?   `ECODE_INE:
                ws_ex_signal == `EX_SIG_IPE ?   `ECODE_IPE:
                ws_ex_signal == `EX_SIG_FPD ?   `ECODE_FPD:
                ws_ex_signal == `EX_SIG_FPE ?   `ECODE_FPE:
            /*ws_ex_signal == `EX_SIG_TLBR?*/   `ECODE_TLBR;
assign EsubCode = ws_ex_signal == `EX_SIG_ADEM ? `ESUBCODE_ADEM : 9'h0;        //只有ADEM的EsubCode是1
assign ws_vaddr = ws_final_result;

reg [`ms_2_ws_bus_wid - 1:0] ms_to_ws_bus_reg;

always @(posedge clk) begin
    if (ws_allowin) begin
        ms_to_ws_bus_reg <= ms_to_ws_bus;
    end
end

assign {
        csr_signal,     //81
        ms_ex,             //1
        ms_ex_signal,   //16
        ms_ertn,           //1
            
        ws_gr_we,
        ws_dest,
        ws_final_result,
        ws_pc   
            } = ms_to_ws_bus_reg;

assign ws_to_id_bus = {
        ws_rf_we,   //38
        rf_we   ,  //37
        rf_waddr,  //36:32
        rf_wdata   //31:0
};

assign ws_ex_out = ws_ex && ws_valid;

assign ws_rf_we = ws_gr_we & ws_valid;
assign ws_ready_go = 1'b1;
assign ws_allowin = (~ws_valid) | ws_ready_go;

always @(posedge clk ) begin
    if (reset) begin
        ws_valid <= 1'b0;
    end
    if (ws_ex_out || ws_ertn_flush)
        ws_valid <= 1'b0;
    else if (ws_allowin) begin
        ws_valid <= ms_to_ws_valid;
    end
end

assign rf_we    = ws_gr_we && ws_valid && !ws_ex;
assign rf_waddr = ws_dest;
assign rf_wdata = csr_re ? csr_rvalue : ws_final_result;

// debug info generate
assign debug_wb_pc       = ws_pc;
assign debug_wb_rf_we   = {4{rf_we}};
assign debug_wb_rf_wnum  = rf_waddr;
assign debug_wb_rf_wdata = rf_wdata;

endmodule